package org.as3search.criteria {
	/*
	 * as3search - http://code.google.com/p/as3search
	 * Copyright (c) 2009-2010 by respective authors. All rights reserved.
	 *
	 * This library is free software; you can redistribute it and/or modify it under the
	 * terms of the GNU Lesser General Public License as published by the Free Software
	 * Foundation; either version 2.1 of the License, or (at your option) any later
	 * version.
	 *
	 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
	 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
	 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
	 *
	 * You should have received a copy of the GNU Lesser General Public License along
	 * with this library; if not, write to the Free Software Foundation, Inc.,
	 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
	 */
	
	import flash.errors.IllegalOperationError;
	
	import org.as3search.Search;
	import org.as3search.config.SearchConfiguration;
	import org.as3search.config.SearchConfigurationAware;
	import org.as3search.properties.PropertyResolver;
	

	/**
	 * <code>SimpleExpression</code> is an abstract base class for 
	 * building <code>Criterion</code> implementations. It is tailored
	 * to comparing a property of an object to a value, not necessarily
	 * to comparing two properties or other comparisons. 
	 * 
	 * @see org.as3search.criteria.Criterion
	 * @see org.as3search.config.SearchConfigurationAware
	 */
	public class SimpleExpression implements Criterion, SearchConfigurationAware {
		
		private var _propertyName:String;
		
		private var _value:Object;
		
		private var _ignoreCase:Boolean;
		
		private var _configuration:SearchConfiguration;
		/**
		 * Creates a new <code>SimpleExpression</code> instance.
		 * @param	propertyName	The name of the property to compare against <code>value</code>.
		 * @param	value			The value to be compared against the value of <code>propertyName</code>.
		 * @param	configuration	The <code>SearchConfiguration</code> to assist in collection comparison and property resolution.
		 * @param	ignoreCase		For String values, whether to ignore capitalization in comparison.
		 */
		public function SimpleExpression(propertyName:String, value:Object, configuration:SearchConfiguration = null,
				ignoreCase:Boolean = false) {
			_propertyName = propertyName;
			_value = value;
			_ignoreCase = ignoreCase;
			_configuration = configuration == null ? Search.configuration : configuration;
		}
		/**
		 * @inheritDoc
		 */
		public function evaluate(value:Object):Boolean {			
			return evaluateProperty(configuration.propertyResolver.resolveProperty(propertyName, value));
		}
		/**
		 * Evaluates the property specified by <code>propertyValue</code>. 
		 * Subclasses should override this method for all property to value
		 * comparisons rather than overriding <code>evaluate()</code>. <code>
		 * evaluate()</code>, in its default configuration in <code>SimpleExpression</code>,
		 * calls this method as a hook to evaluate all values.
		 * @param	propertyValue	The value of the property specified by <code>propertytName</code>.
		 * @return	Returns true if the property value is valid, false otherwise.
		 */
		public function evaluateProperty(propertyValue:Object):Boolean {
			throw new IllegalOperationError("This method must be overridden in a subclass.");
			return false;
		}
		/**
		 * The name of the property to be evaluated on each object.
		 */
		public function get propertyName():String { return _propertyName; }
		/**
		 * The comparison value which the value of <code>propertyName</code> will be 
		 * compared against.
		 */
		public function get value():Object { return _value; }
		/**
		 * For String values, whether to ignore capitalization in comparisons.
		 */
		public function get ignoreCase():Boolean { return _ignoreCase; }
		/**
		 * The <code>PropertyResolver</code> by which to resolve properties in calling
		 * <code>evaluateProperty()</code>.
		 */
		public function get propertyResolver():PropertyResolver { return configuration.propertyResolver; }
		/**
		 * The <code>SearchConfiguration</code> for this instance to use in 
		 * complex comparisons and property resolution.
		 */
		public function get configuration():SearchConfiguration { return _configuration; }
		public function set configuration(value:SearchConfiguration):void { 
			if (value == null)
				value = Search.configuration;
			
			_configuration = value;
		}
	} 
}